#ifndef CODE_SOURCE_NETWORK_SESSION_H_
#define CODE_SOURCE_NETWORK_SESSION_H_

#include "os/socket.h"
#include "base/net/i_session.h"
#include "base/core/raw_allocator.h"
#include "base/core/double_list.h"
#include "buffer.h"
#include "net_define.h"

class Session : public ISession 
{
protected:
	typedef Buffer<RawAllocator>  BUFFER;

	SessionState m_state;
	EventData    m_eventData;
	uint64_t     m_startTime;
	uint64_t     m_activeTime;
	SOCKET       m_socket;
	BUFFER       m_recvBuffer;
	BUFFER       m_sendBuffer;
	SESSION_USER_DATA m_userData;
	DoubleNode   m_lruNode;
	IP_ADDRESS   m_remote;
	uint16_t     m_localPort;
	uint16_t     m_mark;
	uint32_t     m_timeout;
	bool         m_encrypt;
	bool		 m_isShutDown;

public:
    Session();
    ~Session();

    bool Init(SocketFlag  flag,
              SOCKET      sock,
              uint16_t    local_port,
              uint64_t    start_time,
              RawAllocator* alloc,
              void*       handle,
              EventDataEx* data);
    bool UnInit();

    bool Close();
    int  Shutdown();
    bool Send(const char* buf, uint32_t len, bool raw);
    int  Recv(uint64_t tick_ms);
    bool ReadRecvData(uint32_t len);

	virtual uint32_t GetReadSize() { return m_recvBuffer.GetSize(); }
	virtual uint32_t GetWriteSize(){ return m_sendBuffer.GetSize(); }
	virtual uint32_t GetWriteOffset() { return m_sendBuffer.GetWriteSpace(); }
	virtual uint32_t GetReadLen() { return m_sendBuffer.GetReadLength(); }

    bool        IsWorking();    
    bool        IsSendComplete();
    bool        IsFreeTimeout();
    bool        IsTimeout(uint64_t tick_ms);
    void        SetTimeout(uint32_t tm);

    SOCKET      GetSocket();
    SocketFlag  GetSocketFlag();
    EventData*  GetEventData();
    DoubleNode* GetListNode();
    uint32_t    GetTimeout();
    uint64_t    GetActiveTime();
    bool        GetRecvData(char** data, uint32_t* len);
    void*       GetSubpackage();

public:
    virtual void GetUserReq(void** retReq, void** retContext) override;
    virtual void SetUserReq(void* req, void* context) override;

    virtual const SESSION_USER_DATA& GetUserData() override;
    virtual void SetUserData(const SESSION_USER_DATA& data) override;

    virtual void* GetNetPackHandle() override;
    virtual void  SetNetPackHandle(void* netpackhandle) override;

    virtual const IP_ADDRESS& GetRemoteAddress() override;
    virtual uint16_t GetLocalPort() override;

    virtual uint16_t GetMark() override;
    virtual void SetMark(uint16_t mark) override;

    virtual bool GetEncrypt() override;
    virtual void SetEncrypt(bool encrypt) override;
};

#endif  // CODE_SOURCE_NETWORK_SESSION_H_
